home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH24 / FSPSGDI.ASM next >
Encoding:
Assembly Source File  |  1994-07-28  |  15.9 KB  |  839 lines

  1.         .286
  2.         page    58, 132
  3.         name    FSPSGDI
  4.         title    FSPSGDI (CH Products Standard Game Device Interface).
  5.  
  6. ; CHSGDI.EXE
  7. ;
  8. ;    Usage:
  9. ;        CHSDGI    {LEFT}
  10. ;
  11. ; This program loads a TSR which patches INT 15 so arbitrary game programs
  12. ; can read the CH Products FlightStick Pro joystick in a portable fashion.
  13.  
  14.  
  15. wp        equ    <word ptr>
  16. byp        equ    <byte ptr>
  17.  
  18.  
  19.  
  20. ; We need to load cseg in memory before any other segments!
  21.  
  22. cseg        segment    para public 'code'
  23. cseg        ends
  24.  
  25.  
  26. ; Initialization code, which we do not need except upon initial load,
  27. ; goes in the following segment:
  28.  
  29. Initialize    segment    para public 'INIT'
  30. Initialize    ends
  31.  
  32. ; UCR Standard Library routines which get dumped later on.
  33.  
  34.         .xlist
  35.         include        stdlib.a
  36.         includelib    stdlib.lib
  37.         .list
  38.  
  39. sseg        segment    para stack 'stack'
  40. sseg        ends
  41.  
  42. zzzzzzseg    segment    para public 'zzzzzzseg'
  43. zzzzzzseg    ends
  44.  
  45.  
  46.  
  47. CSEG        segment    para public 'CODE'
  48.         assume    cs:cseg, ds:nothing
  49.  
  50. Int15Vect    dd    0
  51.  
  52. PSP        dw    ?
  53.  
  54. ; Port addresses for a typical joystick card:
  55.  
  56. JoyPort        equ    201h
  57. JoyTrigger    equ    201h
  58.  
  59.  
  60. CurrentReading    dw    0
  61.  
  62. Pot        struc
  63. PotMask        db    0            ;Pot mask for hardware.
  64. DidCal        db    0            ;Is this pot calibrated?
  65. min        dw    5000            ;Minimum pot value
  66. max        dw    0            ;Max pot value
  67. center        dw    0            ;Pot value in the middle
  68. Pot        ends
  69.  
  70. Pot0        Pot    <1>
  71. Pot1        Pot    <2>
  72. Pot3        Pot    <8>
  73.  
  74.  
  75. ; SwapButtons-    0 if we should use normal flightstick pro buttons,
  76. ;        1 if we should swap the left and right buttons.
  77.  
  78. SwapButtons    byte    0
  79.  
  80. ; SwBits- the four bit input value from the Flightstick Pro selects one
  81. ;      of the following bit patterns for a given switch position.
  82.  
  83. SwBits        byte    10h        ;Sw4
  84.         byte    0        ;NA
  85.         byte    0        ;NA
  86.         byte    0        ;NA
  87.         byte    40h        ;Sw6
  88.         byte    0        ;NA
  89.         byte    0        ;NA
  90.         byte    4        ;Sw 2
  91.  
  92.         byte    80h        ;Sw 7
  93.         byte    0        ;NA
  94.         byte    0        ;NA
  95.         byte    8        ;Sw 3
  96.         byte    20h        ;Sw 5
  97.         byte    2        ;Sw 1
  98.         byte    1        ;Sw 0
  99.         byte    0        ;NA
  100.  
  101. SwBitsL        byte    10h        ;Sw4
  102.         byte    0        ;NA
  103.         byte    0        ;NA
  104.         byte    0        ;NA
  105.         byte    40h        ;Sw6
  106.         byte    0        ;NA
  107.         byte    0        ;NA
  108.         byte    4        ;Sw 2
  109.  
  110.         byte    80h        ;Sw 7
  111.         byte    0        ;NA
  112.         byte    0        ;NA
  113.         byte    2        ;Sw 3
  114.         byte    20h        ;Sw 5
  115.         byte    8        ;Sw 1
  116.         byte    1        ;Sw 0
  117.         byte    0        ;NA
  118.  
  119.  
  120.  
  121. ; The IDstring address gets passed back to the caller on a testpresence
  122. ; call.  The four bytes before the IDstring must contain the serial number
  123. ; and current driver number.
  124.  
  125. SerialNumber    db    0,0,0
  126. IDNumber    db    0
  127. IDString    db    "CH Products:Flightstick Pro",0
  128.         db    "Written by Randall Hyde",0
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135. ;============================================================================
  136. ;
  137. ; ReadPots- AH contains a bit mask to determine which pots we should read.
  138. ;        Bit 0 is one if we should read pot 0, bit 1 is one if we should
  139. ;        read pot 1, bit 3 is one if we should read pot 3.  All other bits
  140. ;        will be zero.
  141. ;
  142. ;    This code returns the pot values in SI, BX, BP, and DI for Pot 0, 1,
  143. ;    2, & 3.
  144. ;
  145.  
  146. ReadPots    proc    near
  147.         sub    bp, bp
  148.         mov    si, bp
  149.         mov    di, bp
  150.         mov    bx, bp
  151.  
  152. ; Wait for pots to finish any past junk:
  153.  
  154.         mov    dx, JoyPort
  155.         out    dx, al        ;Trigger pots
  156.         mov    cx, 400h
  157. Wait4Pots:    in    al, dx
  158.         and    al, 0Fh
  159.         loopnz    Wait4Pots
  160.  
  161. ; Okay, read the pots:
  162.  
  163.         mov    dx, JoyTrigger
  164.         out    dx, al        ;Trigger pots
  165.         mov    dx, JoyPort
  166.         mov    cx, 8000h    ;Don't let this go on forever.
  167. PotReadLoop:    in    al, dx
  168.         and    al, ah
  169.         jz    PotReadDone
  170.         shr    al, 1
  171.         adc    si, 0
  172.         shr    al, 1
  173.         adc    bp, 0
  174.         shr    al, 2
  175.         adc    di, 0
  176.         loop    PotReadLoop
  177. PotReadDone:
  178.         ret
  179. ReadPots    endp
  180.  
  181.  
  182.  
  183. ;----------------------------------------------------------------------------
  184. ;
  185. ; Normalize-     BX contains a pointer to a pot structure, AX contains
  186. ;        a pot value.  Normalize that value according to the
  187. ;        calibrated pot.
  188. ;
  189. ; Note: DS must point at cseg before calling this routine.
  190.  
  191.  
  192.         assume    ds:cseg
  193. Normalize    proc    near
  194.         push    cx
  195.  
  196. ; Sanity check to make sure the calibration process went okay.
  197.  
  198.         cmp    [bx].Pot.DidCal, 0
  199.         je    BadNorm
  200.         mov    dx, [bx].Pot.Center
  201.         cmp    dx, [bx].Pot.Min
  202.         jbe    BadNorm
  203.         cmp    dx, [bx].Pot.Max
  204.         jae    BadNorm
  205.  
  206. ; Clip the value if it is out of range.
  207.  
  208.         cmp    ax, [bx].Pot.Min
  209.         ja    MinOkay
  210.         mov    ax, [bx].Pot.Min
  211. MinOkay:
  212.  
  213.         cmp    ax, [bx].Pot.Max
  214.         jb    MaxOkay
  215.         mov    ax, [bx].Pot.Max
  216. MaxOkay:
  217.  
  218. ; Scale this guy around the center:
  219.  
  220.         cmp    ax, [bx].Pot.Center
  221.         jb    Lower128
  222.  
  223. ; Scale in the range 128..255 here:
  224.  
  225.         sub    ax, [bx].Pot.Center
  226.         mov    dl, ah        ;Multiply by 128
  227.         mov    ah, al
  228.         mov    dh, 0
  229.         mov    al, dh
  230.         shr    dl, 1
  231.         rcr    ax, 1
  232.         mov    cx, [bx].Pot.Max
  233.         sub    cx, [bx].Pot.Center
  234.         jz    BadNorm        ;Prevent division by zero.
  235.         div    cx        ;Compute normalized value.
  236.         add    ax, 128        ;Scale to range 128..255.
  237.         cmp    ah, 0
  238.         je    NormDone
  239.         mov    ax, 0ffh    ;Result must fit in 8 bits!
  240.         jmp    NormDone
  241.  
  242. ; Scale in the range 0..127 here:
  243.  
  244. Lower128:    sub    ax, [bx].Pot.Min
  245.         mov    dl, ah        ;Multiply by 128
  246.         mov    ah, al
  247.         mov    dh, 0
  248.         mov    al, dh
  249.         shr    dl, 1
  250.         rcr    ax, 1
  251.         mov    cx, [bx].Pot.Center
  252.         sub    cx, [bx].Pot.Min
  253.         jz    BadNorm
  254.         div    cx        ;Compute normalized value.
  255.         cmp    ah, 0
  256.         je    NormDone
  257.         mov    ax, 0ffh    ;Result must fit in 8 bits!
  258.         jmp    NormDone
  259.  
  260. BadNorm:    sub    ax, ax
  261. NormDone:    pop    cx
  262.         ret
  263. Normalize    endp
  264.         assume    ds:nothing
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272. ;============================================================================
  273. ; INT 15h handler functions.
  274. ;============================================================================
  275. ;
  276. ; Although these are defined as near procs, they are not really procedures.
  277. ; The MyInt15 code jumps to each of these with BX, a far return address, and
  278. ; the flags sitting on the stack.  Each of these routines must handle the
  279. ; stack appropriately.
  280. ;
  281. ;----------------------------------------------------------------------------
  282. ; BIOS- Handles the two BIOS calls, DL=0 to read the switches, DL=1 to
  283. ;    read the pots.  For the BIOS routines, we'll ignore the cooley
  284. ;    switch (the hat) and simply read the other four switches.
  285.  
  286. BIOS        proc    near
  287.         cmp    dl, 1        ;See if switch or pot routine.
  288.         jb    Read4Sw
  289.         je    ReadBIOSPots
  290.         pop    bx
  291.         jmp    cs:Int15Vect    ;Let someone else handle it!
  292.  
  293. Read4Sw:    push    dx
  294.         mov    dx, JoyPort
  295.         in    al, dx
  296.         shr    al, 4
  297.         mov    bl, al
  298.         mov    bh, 0
  299.         cmp    cs:SwapButtons, 0
  300.         je    DoLeft2
  301.         mov    al, cs:SwBitsL[bx]
  302.         jmp    SBDone
  303.  
  304. DoLeft2:    mov    al, cs:SwBits[bx]
  305. SBDone:        rol    al, 4        ;Put Sw0..3 in upper bits and make
  306.         not    al        ; 0=switch down, just like game card.
  307.         pop    dx
  308.         pop    bx
  309.         iret
  310.  
  311. ReadBIOSPots:    pop    bx        ;Return a value in BX!
  312.         push    si
  313.         push    di
  314.         push    bp
  315.         mov    ah, 0bh
  316.         call    ReadPots
  317.         mov    ax, si
  318.         mov    bx, bp
  319.         mov    dx, di
  320.         sub    cx, cx
  321.         pop    bp
  322.         pop    di
  323.         pop    si
  324.         iret
  325. BIOS        endp
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332. ;----------------------------------------------------------------------------
  333. ;
  334. ; ReadPot-    On entry, DL contains a pot number to read.
  335. ;        Read and normalize that pot and return the result in AL.
  336.  
  337.         assume    ds:cseg
  338. ReadPot        proc    near
  339. ;;;;;;;;;;    push    bx        ;Already on stack.
  340.         push    ds
  341.         push    cx
  342.         push    dx
  343.         push    si
  344.         push    di
  345.         push    bp
  346.  
  347.         mov    bx, cseg
  348.         mov    ds, bx
  349.  
  350.         cmp    dl, 0
  351.         jne    Try1
  352.         mov    ah, Pot0.PotMask
  353.         call    ReadPots
  354.         lea    bx, Pot0
  355.         mov    ax, si
  356.         call    Normalize
  357.         jmp    GotPot
  358.  
  359. Try1:        cmp    dl, 1
  360.         jne    Try3
  361.         mov    ah, Pot1.PotMask
  362.         call    ReadPots
  363.         lea    bx, Pot1
  364.         mov    ax, bp
  365.         call    Normalize
  366.         jmp    GotPot
  367.  
  368. Try3:        cmp    dl, 3
  369.         jne    BadPot
  370.         mov    ah, Pot3.PotMask
  371.         call    ReadPots
  372.         lea    bx, Pot3
  373.         mov    ax, di
  374.         call    Normalize
  375.         jmp    GotPot
  376.  
  377. BadPot:        sub    ax, ax        ;Question: Should we pass this on
  378.                     ; or just return zero?
  379. GotPot:        pop    bp
  380.         pop    di
  381.         pop    si
  382.         pop    dx
  383.         pop    cx
  384.         pop    ds
  385.         pop    bx
  386.         iret
  387. ReadPot        endp
  388.         assume    ds:nothing
  389.  
  390.  
  391. ;----------------------------------------------------------------------------
  392. ;
  393. ; ReadRaw-    On entry, DL contains a pot number to read.
  394. ;        Read that pot and return the unnormalized result in AL.
  395.  
  396.         assume    ds:cseg
  397. ReadRaw        proc    near
  398. ;;;;;;;;;;    push    bx        ;Already on stack.
  399.         push    ds
  400.         push    cx
  401.         push    dx
  402.         push    si
  403.         push    di
  404.         push    bp
  405.  
  406.         mov    bx, cseg
  407.         mov    ds, bx
  408.  
  409.         cmp    dl, 0
  410.         jne    Try1
  411.         mov    ah, Pot0.PotMask
  412.         call    ReadPots
  413.         mov    ax, si
  414.         jmp    GotPot
  415.  
  416. Try1:        cmp    dl, 1
  417.         jne    Try3
  418.         mov    ah, Pot1.PotMask
  419.         call    ReadPots
  420.         mov    ax, bp
  421.         jmp    GotPot
  422.  
  423. Try3:        cmp    dl, 3
  424.         jne    BadPot
  425.         mov    ah, Pot3.PotMask
  426.         call    ReadPots
  427.         mov    ax, di
  428.         jmp    GotPot
  429.  
  430. BadPot:        sub    ax, ax        ;Question: Should we pass this on
  431.                     ; or just return zero?
  432. GotPot:        pop    bp
  433.         pop    di
  434.         pop    si
  435.         pop    dx
  436.         pop    cx
  437.         pop    ds
  438.         pop    bx
  439.         iret
  440. ReadRaw        endp
  441.         assume    ds:nothing
  442.  
  443.  
  444. ;----------------------------------------------------------------------------
  445. ; Read4Pots-    Reads pots zero, one, two, and three returning their
  446. ;        values in AL, AH, DL, and DH.  Since the flightstick
  447. ;        Pro doesn't have a pot 2 installed, return zero for
  448. ;        that guy.
  449.  
  450. Read4Pots    proc    near
  451. ;;;;;;;;;;;    push    bx        ;Already on stack
  452.         push    ds
  453.         push    cx
  454.         push    si
  455.         push    di
  456.         push    bp
  457.  
  458.         mov    dx, cseg
  459.         mov    ds, dx
  460.  
  461.         mov    ah, 0bh        ;Read pots 0, 1, and 3.
  462.         call    ReadPots
  463.  
  464.         mov    ax, si
  465.         lea    bx, Pot0
  466.         call    Normalize
  467.         mov    cl, al
  468.  
  469.         mov    ax, bp
  470.         lea    bx, Pot1
  471.         call    Normalize
  472.         mov    ch, al
  473.  
  474.         mov    ax, di
  475.         lea    bx, Pot3
  476.         call    Normalize
  477.         mov    dh, al        ;Pot 3 value.
  478.         mov    ax, cx        ;Pots 0 and 1.
  479.         mov    dl, 0        ;Pot 2 is non-existant.
  480.  
  481.         pop    bp
  482.         pop    di
  483.         pop    si
  484.         pop    cx
  485.         pop    ds
  486.         pop    bx
  487.         iret
  488. Read4Pots    endp
  489.  
  490.  
  491.  
  492.  
  493. ;----------------------------------------------------------------------------
  494. ; CalPot-    Calibrate the pot specified by DL.  On entry, AL contains
  495. ;        the minimum pot value (it better be less than 256!), BX
  496. ;        contains the maximum pot value, and CX contains the centered
  497. ;        pot value.
  498.  
  499.         assume    ds:cseg
  500. CalPot        proc    near
  501.         pop    bx        ;Retrieve maximum value
  502.         push    ds
  503.         push    si
  504.         mov    si, cseg
  505.         mov    ds, si
  506.  
  507. ; Sanity check on parameters, sort them in ascending order:
  508.  
  509.         mov    ah, 0
  510.         cmp    bx, cx
  511.         ja    GoodMax
  512.         xchg    bx, cx
  513. GoodMax:    cmp    ax, cx
  514.         jb    GoodMin
  515.         xchg    ax, cx
  516. GoodMin:    cmp    cx, bx
  517.         jb    GoodCenter
  518.         xchg    cx, bx
  519. GoodCenter:
  520.  
  521.  
  522. ; Okay, figure out who were supposed to calibrate:
  523.  
  524.         lea    si, Pot0
  525.         cmp    dl, 1
  526.         jb    DoCal
  527.         lea    si, Pot1
  528.         je    DoCal
  529.         cmp    dl, 3
  530.         jne    CalDone
  531.         lea    si, Pot3
  532.  
  533. DoCal:        mov    [si].Pot.min, ax
  534.         mov    [si].Pot.max, bx
  535.         mov    [si].Pot.center, cx
  536.         mov    [si].Pot.DidCal, 1
  537. CalDone:    pop    si
  538.         pop    ds
  539.         iret
  540. CalPot        endp
  541.         assume    ds:nothing
  542.  
  543.  
  544. ;----------------------------------------------------------------------------
  545. ; TestCal-    Just checks to see if the pot specified by DL has already
  546. ;        been calibrated.
  547.  
  548.         assume    ds:cseg
  549. TestCal        proc    near
  550. ;;;;;;;;    push    bx        ;Already on stack
  551.         push    ds
  552.         mov    bx, cseg
  553.         mov    ds, bx
  554.  
  555.         sub    ax, ax        ;Assume no calibration
  556.         lea    bx, Pot0
  557.         cmp    dl, 1
  558.         jb    GetCal
  559.         lea    bx, Pot1
  560.         je    GetCal
  561.         cmp    dl, 3
  562.         jne    BadCal
  563.         lea    bx, Pot3
  564.  
  565. GetCal:        mov    al, [bx].Pot.DidCal
  566.         mov    ah, 0
  567. BadCal:        pop    ds
  568.         pop    bx
  569.         iret
  570. TestCal        endp
  571.         assume    ds:nothing
  572.  
  573.  
  574. ;----------------------------------------------------------------------------
  575. ;
  576. ; ReadSw-    Reads the switch whose switch number appears in DL.
  577.  
  578. SwTable        byte    11100000b, 11010000b, 01110000b, 10110000b
  579.         byte    00000000b, 11000000b, 01000000b, 10000000b
  580.  
  581. SwTableL    byte    11100000b, 10110000b, 01110000b, 11010000b
  582.         byte    00000000b, 11000000b, 01000000b, 10000000b
  583.  
  584. ReadSw        proc    near
  585. ;;;;;;;        push    bx        ;Already on stack
  586.         mov    bl, dl        ;Save switch to read.
  587.         mov    bh, 0
  588.         mov    dx, JoyPort
  589.         in    al, dx
  590.         and      al, 0f0h
  591.         cmp    cs:SwapButtons, 0
  592.         je    DoLeft0
  593.         cmp    al, cs:SwTableL[bx]
  594.         jne    NotDown
  595.         jmp    IsDown
  596.  
  597. DoLeft0:    cmp    al, cs:SwTable[bx]
  598.         jne    NotDown
  599.  
  600. IsDown:        mov    ax, 1
  601.         pop    bx
  602.         iret
  603.  
  604. NotDown:    sub    ax, ax
  605.         pop    bx
  606.         iret
  607. ReadSw        endp
  608.  
  609.  
  610. ;----------------------------------------------------------------------------
  611. ;
  612. ; Read16Sw-    Reads all eight switches and returns their values in AX.
  613.  
  614. Read16Sw    proc    near
  615. ;;;;;;;;    push    bx        ;Already on stack
  616.         mov    ah, 0        ;Switches 8-15 are non-existant.
  617.         mov    dx, JoyPort
  618.         in    al, dx
  619.         shr    al, 4
  620.         mov    bl, al
  621.         mov    bh, 0
  622.         cmp    cs:SwapButtons, 0
  623.         je    DoLeft1
  624.         mov    al, cs:SwBitsL[bx]
  625.         jmp    R8Done
  626.  
  627. DoLeft1:    mov    al, cs:SwBits[bx]
  628. R8Done:        pop    bx
  629.         iret
  630. Read16Sw    endp
  631.  
  632.  
  633. ;****************************************************************************
  634. ;
  635. ; MyInt15-    Patch for the BIOS INT 15 routine to control reading the
  636. ;        joystick.
  637.  
  638. MyInt15        proc    far
  639.         push    bx
  640.         cmp    ah, 84h            ;Joystick code?
  641.         je    DoJoystick
  642. OtherInt15:    pop    bx
  643.         jmp    cs:Int15Vect
  644.  
  645. DoJoystick:    mov    bh, 0
  646.         mov    bl, dh
  647.         cmp    bl, 80h
  648.         jae    VendorCalls
  649.         cmp    bx, JmpSize
  650.         jae    OtherInt15
  651.         shl    bx, 1
  652.         jmp    wp cs:jmptable[bx]
  653.  
  654. jmptable    word    BIOS
  655.         word    ReadPot, Read4Pots, CalPot, TestCal
  656.         word    ReadRaw, OtherInt15, OtherInt15
  657.         word    ReadSw, Read16Sw
  658. JmpSize        =    ($-jmptable)/2
  659.  
  660.  
  661. ; Handle vendor specific calls here.
  662.  
  663. VendorCalls:    je    RemoveDriver
  664.         cmp    bl, 81h
  665.         je    TestPresence
  666.         pop    bx
  667.         jmp    cs:Int15Vect
  668.  
  669. ; TestPresence- Returns zero in AX and a pointer to the ID string in ES:BX
  670.  
  671. TestPresence:    pop    bx        ;Get old value off stack.
  672.         sub    ax, ax
  673.         mov    bx, cseg
  674.         mov    es, bx
  675.         lea    bx, IDString
  676.         iret
  677.  
  678. ; RemoveDriver- If there are no other drivers loaded after this one in
  679. ;        memory, disconnect it and remove it from memory.
  680.  
  681. RemoveDriver:
  682.         push    ds
  683.         push    es
  684.         push    ax
  685.         push    dx
  686.  
  687.         mov    dx, cseg
  688.         mov    ds, dx
  689.  
  690. ; See if we're the last routine patched into INT 15h
  691.  
  692.         mov    ax, 3515h
  693.         int    21h
  694.         cmp    bx, offset MyInt15
  695.         jne    CantRemove
  696.         mov    bx, es
  697.         cmp    bx, wp seg MyInt15
  698.         jne    CantRemove
  699.  
  700.         mov    ax, PSP            ;Free the memory we're in
  701.         mov    es, ax
  702.         push    es
  703.         mov    ax, es:[2ch]         ;First, free env block.
  704.         mov    es, ax
  705.         mov    ah, 49h
  706.         int    21h
  707. ;
  708.         pop    es            ;Now free program space.
  709.         mov    ah, 49h
  710.         int    21h
  711.  
  712.         lds    dx, Int15Vect        ;Restore previous int vect.
  713.         mov    ax, 2515h
  714.         int    21h
  715.  
  716. CantRemove:    pop    dx
  717.         pop    ax
  718.         pop    es
  719.         pop    ds
  720.         pop    bx
  721.         iret
  722. MyInt15        endp
  723. cseg        ends
  724.  
  725.  
  726.  
  727. ; The following segment is tossed when this code goes resident.
  728.  
  729. Initialize    segment    para public 'INIT'
  730.         assume    cs:Initialize, ds:cseg
  731. Main        proc
  732.         mov    ax, cseg        ;Get ptr to vars segment
  733.         mov    es, ax
  734.         mov    es:PSP, ds        ;Save PSP value away
  735.         mov    ds, ax
  736.  
  737.         mov    ax, zzzzzzseg
  738.         mov    es, ax
  739.         mov    cx, 100h
  740.         meminit2
  741.  
  742.         print
  743.         byte    "╓───────────────────────────────────────╖",cr,lf
  744.         byte    "║ Standard Game Device Interface driver ║",cr,lf
  745.         byte    "║ CH Products Flightstick Pro           ║",cr,lf
  746.         byte    "║ Written by Randall Hyde               ║",cr,lf
  747.         byte    "╙───────────────────────────────────────╜",cr,lf
  748.         byte    cr,lf
  749.         byte    "'FSPSGDI LEFT' swaps the left and right buttons for "
  750.         byte    "left handed players",cr,lf
  751.         byte    "'FSPSGDI REMOVE' removes the driver from memory",cr,lf
  752.         byte    lf
  753.         byte    0
  754.  
  755.         mov    ax, 1
  756.         argv                ;If no parameters, empty str.
  757.         stricmpl
  758.         byte    "LEFT",0
  759.         jne    NoLEFT
  760.         mov    SwapButtons, 1
  761.         print
  762.         byte    "Left and right buttons swapped",cr,lf,0
  763.         jmp    SwappedLeft
  764.  
  765. NoLEFT:        stricmpl
  766.         byte    "REMOVE",0
  767.         jne    NoRmv
  768.         mov    dh, 81h
  769.         mov    ax, 84ffh
  770.         int    15h        ;See if we're already loaded.
  771.         test    ax, ax        ;Get a zero back?
  772.         jz    Installed
  773.         print
  774.         byte    "SGDI driver is not present in memory, REMOVE "
  775.         byte    "command ignored.",cr,lf,0
  776.         mov    ax, 4c01h    ;Exit to DOS.
  777.         int    21h
  778.  
  779. Installed:    mov    ax, 8400h
  780.         mov    dh, 80h        ;Remove call
  781.         int     15h
  782.         mov    ax, 8400h
  783.         mov    dh, 81h        ;TestPresence call
  784.         int    15h
  785.         cmp    ax, 0
  786.         je    NotRemoved
  787.         print
  788.         byte    "Successfully removed SGDI driver from memory."
  789.         byte    cr,lf,0
  790.         mov    ax, 4c01h    ;Exit to DOS.
  791.         int    21h
  792.  
  793. NotRemoved:    print
  794.         byte    "SGDI driver is still present in memory.",cr,lf,0
  795.         mov    ax, 4c01h    ;Exit to DOS.
  796.         int    21h
  797.  
  798.  
  799.  
  800. NoRmv:
  801.  
  802.  
  803. ; Okay, Patch INT 15 and go TSR at this point.
  804.  
  805. SwappedLeft:    mov    ax, 3515h
  806.         int    21h
  807.         mov    wp Int15Vect, bx
  808.         mov    wp Int15Vect+2, es
  809.  
  810.         mov    dx, cseg
  811.         mov    ds, dx
  812.         mov    dx, offset MyInt15
  813.         mov    ax, 2515h
  814.         int    21h
  815.  
  816.         mov    dx, cseg
  817.         mov    ds, dx
  818.         mov    dx, seg Initialize
  819.         sub    dx, ds:psp
  820.         add    dx, 2
  821.         mov    ax, 3100h        ;Do TSR
  822.         int    21h
  823. Main        endp
  824.  
  825. Initialize    ends
  826.  
  827. sseg        segment    para stack 'stack'
  828.         dw    128 dup (0)
  829. endstk        dw    ?
  830. sseg        ends
  831.  
  832. zzzzzzseg    segment    para public 'zzzzzzseg'
  833.         db     16 dup (0)
  834. zzzzzzseg    ends
  835.  
  836.  
  837.  
  838.         end    Main
  839.